<?php
/**
 * Description: 店员管理
 * Author: hezhizheng
 * Date: 2018/7/18
 * Time: 9:13
 * Created by Created by Panxsoft.
 */

namespace App\Http\Controllers\App;

use App\Exceptions\ApiErrCode;
use App\Http\Controllers\ApiController;
use App\Http\Requests\App\StaffStoreRequest;
use App\Http\Requests\App\StaffUpdateRequest;
use App\Models\Admin\StoreAdmin;
use App\Models\OpenWechat\ScanEvent;
use App\Models\OpenWechat\WechatUser;
use App\Models\Store\Store;
use App\Services\OpenWechat\QrCode;
use App\Services\Utils\Guard;
use App\Services\Utils\RequestParam;
use App\Services\Utils\SimpleQrCode;
use Illuminate\Http\Request;

class StaffController extends ApiController
{
    const ROUTES = [
        'index'           => 'app.staff.index',
        'store'           => 'app.staff.store',
        'destroy'         => 'app.staff.destroy',
        'update'          => 'app.staff.update',
        'binding_qr_code' => 'app.staff.binding_qr_code',
        'binding_poll'    => 'app.staff.binding_poll',
    ];

    /**
     *
     * 查看当前店铺店员（StoreAdmin）列表（不显示停用的店员）
     * @test
     *
     * @return array|\Illuminate\Http\Response
     */
    public function index()
    {
        $device_account = Guard::deviceAccount();

        $store = $device_account->store;

        $staffs = $store->storeAdmins()
            ->role(StoreAdmin::STAFF)
            ->where('is_deleted', StoreAdmin::IS_NOT_DELETED)
            ->with(['wechatUser'])
            ->latest()
            ->get();

        $staffs->transform(function (StoreAdmin $storeAdmin) {
            $storeAdmin->received_consumer_count = $storeAdmin->skinRecords()
                ->pluck('wechat_user_id')
                ->unique()
                ->count(); // 接待客户数
            return $storeAdmin;
        });

        return $this->response(compact('staffs'));
    }

    /**
     * 绑定店员二维码
     * @test
     *
     * @param Request $request
     * @return array|\Illuminate\Contracts\Routing\ResponseFactory|\Illuminate\Http\Response|\Symfony\Component\HttpFoundation\Response
     * @throws \Exception
     */
    public function bindingQrCode(Request $request)
    {
        $deviceAccount = Guard::deviceAccount();

        /** @var Store $store */
        $store = $deviceAccount->store;
        $authorizer = $store->getAuthorizer();
        $this->checkItemExist($authorizer, trans('admin.authorizer'));

        $scan_event = ScanEvent::createNewEvent(
            ScanEvent::TYPE_APP_STORE_STAFF_BIND,
            null
        );

        $qr_result = QrCode::generate(
            $authorizer->authorizer_appid,
            $scan_event->getSceneValue()
        );
        $this->checkQrResult($qr_result);

        $url = $qr_result['url'];
        if ($request->type === 'png') {
            return $this->responseImage(SimpleQrCode::toImage($url));
        }

        $code_img_url = QrCode::ticketToQrCodeUrl($authorizer->authorizer_appid, $qr_result['ticket']);
        $scan_event_id = $scan_event->id;

        return $this->response(compact('url', 'scan_event_id', 'code_img_url'));
    }

    /**
     * app 轮询是否已经扫码
     * @test
     *
     * @param $scan_event_id
     *
     * @return array|\Illuminate\Http\Response
     * @throws \Exception
     */
    public function bindingPoll($scan_event_id)
    {
        $scan_event = ScanEvent::find($scan_event_id);
        $this->checkItemExist($scan_event, trans('app.scan_event_error'));
        $this->checkIsTrue(
            $scan_event->isScanned(), trans('app.check_can_operate'),
            ApiErrCode::APP_STAFF_SCAN_EVT_NOT_FOUND
        );

        $wechat_user = WechatUser::find($scan_event->value);
            $this->checkItemExist($wechat_user, trans('app.wechat_user_error'));
            $this->checkUnless($wechat_user->storeAdmin, trans('app.wechat_user_has_been_bound_store_admin'));

        return $this->response(compact('wechat_user'));
    }


    /**
     *
     * 提交绑定的微信ID与店员信息（包括新增的支付宝账号）新增店员
     *
     * @test
     *
     * @param StaffStoreRequest $request
     * @return array|\Illuminate\Http\Response
     * @throws \Exception
     */
    public function store(StaffStoreRequest $request)
    {
        $deviceAccount = Guard::deviceAccount();

        /** @var Store $store */
        $store = $deviceAccount->store;

        $wechat_user_id = (int)$request->wechat_user_id;

        $this->checkStoreWechatUser($wechat_user_id);

        $store_admin = $stored = (new StoreAdmin)->create([
            'store_id'       => $store->id,
            'wechat_user_id' => $wechat_user_id,
            'name'           => $request->name,
            'phone'          => $request->phone,
            'ali_account'    => $request->ali_account,
            'account'        => $request->name . time(),
            'password'       => bcrypt('123456'), // 密码都默认为123456
        ]);

        $store_admin->assignRole(StoreAdmin::STAFF);

        return $this->response(compact('stored'));
    }

    /**
     * 修改店员的信息与绑定的微信
     *
     * @test
     *
     * @param $id
     * @param StaffUpdateRequest $request
     * @return array|\Illuminate\Http\Response
     * @throws \Exception
     */
    public function update($id, StaffUpdateRequest $request)
    {
        $store_admin = (new StoreAdmin)->find($id);
        $this->checkItemExist($store_admin);

        $wechat_user_id = (int)$request->wechat_user_id;

        $this->checkUpdateWechatUser($wechat_user_id, $store_admin);

        // 不修改 account
        $update = $store_admin->update(
            RequestParam::normalize(
                array_keys($request->rules())
            )
        );

        return $this->response(compact('update'));
    }

    /**
     * 删除店员(更新is_deleted状态)
     *
     * @test
     *
     * @param $id
     * @return array|\Illuminate\Http\Response
     * @throws \Exception
     */
    public function destroy($id)
    {
        $store_admin = (new StoreAdmin)
            ->where('is_deleted', StoreAdmin::IS_NOT_DELETED)
            ->find($id);
        $this->checkItemExist($store_admin);

        $destroy = $store_admin->update([
            'is_deleted' => StoreAdmin::IS_DELETED,
        ]);

        return $this->response(compact('destroy'));
    }

    /**
     * @param array $qr_result
     * @throws \Exception
     */
    private function checkQrResult(array $qr_result)
    {
        if (isset($qr_result['errcode'])) {
            $this->checkFailed($qr_result['errmsg'], $qr_result['errcode']);
        }
    }

    /**
     * 验证微信用户是否满足绑定当前店员
     *
     * @param int $wechat_user_id
     * @param StoreAdmin $storeAdmin
     * @return bool
     * @throws \Exception
     */
    private function checkUpdateWechatUser(int $wechat_user_id, StoreAdmin $storeAdmin): bool
    {
        if ($this->isWechatUserIdExist($wechat_user_id) &&
            $this->hasWechatUser($wechat_user_id) &&
            $this->canIgnoreCheckBinding($wechat_user_id, $storeAdmin)
        ) {
            /** @var WechatUser $wechat_user */
            $wechat_user = (new WechatUser)->find($wechat_user_id);
            $this->checkItemExist($wechat_user);
            $this->checkUnless($wechat_user->storeAdmin, trans('app.wechat_user_has_been_bound_store_admin'));
        }
        return true;
    }

    /**
     * @param int $wechat_user_id
     * @return bool
     * @throws \Exception
     */
    private function checkStoreWechatUser(int $wechat_user_id): bool
    {
        if ($this->hasWechatUser($wechat_user_id)) {
            /** @var WechatUser $wechat_user */
            $wechat_user = (new WechatUser)->find($wechat_user_id);
            $this->checkItemExist($wechat_user);
            $this->checkUnless($wechat_user->storeAdmin, trans('app.wechat_user_has_been_bound_store_admin'));
        }

        return true;
    }

    /**
     * 检查是wechat_user_id否有值
     *
     * @param int $wechat_user_id
     * @return bool
     */
    private function isWechatUserIdExist(int $wechat_user_id): bool
    {
        return (bool)$wechat_user_id;
    }

    /**
     * 检查是否有微信用户
     * @param int $wechat_user_id
     * @return bool
     */
    private function hasWechatUser(int $wechat_user_id): bool
    {
        return $wechat_user_id !== 0;
    }

    /**
     * 检查是否可以忽略本次微信用户与店员绑定的验证
     *
     * @param int $wechat_user_id
     * @param StoreAdmin $store_admin
     * @return bool
     */
    private function canIgnoreCheckBinding(int $wechat_user_id, StoreAdmin $store_admin): bool
    {
        return $wechat_user_id !== $store_admin->wechat_user_id;
    }
}